<template>
  <div class="fixed inset-0 flex items-end justify-center px-4 py-6 pointer-events-none sm:p-6 z-50">
    <div 
      v-for="(toast, index) in toasts" 
      :key="index"
      :class="[
        'max-w-sm w-full shadow-lg rounded-lg pointer-events-auto transition-all duration-300 transform',
        toast.type === 'success' ? 'bg-green-50 border-l-4 border-green-500' :
        toast.type === 'error' ? 'bg-red-50 border-l-4 border-red-500' :
        toast.type === 'info' ? 'bg-blue-50 border-l-4 border-blue-500' :
        'bg-yellow-50 border-l-4 border-yellow-500',
        index === 0 ? 'translate-y-0 opacity-100' : `-translate-y-${index * 4} opacity-75`,
        toast.type === 'error' ? 'animate-bounce-small' : '',
        {'opacity-0 translate-y-2': toast.isExiting}
      ]"
      style="margin-bottom: 0.75rem;"
      @mouseenter="pauseTimer(toast.id)"
      @mouseleave="resumeTimer(toast.id)"
    >
      <div class="p-4" :class="{'error-toast': toast.type === 'error'}">
        <div class="flex items-start">
          <div>
            <svg 
              v-if="toast.type === 'success'" 
              class="h-6 w-6 text-green-500" 
              xmlns="http://www.w3.org/2000/svg" 
              fill="none" 
              viewBox="0 0 24 24" 
              stroke="currentColor"
            >
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
            </svg>
            <svg 
              v-else-if="toast.type === 'error'" 
              class="h-6 w-6 text-red-500 animate-pulse" 
              xmlns="http://www.w3.org/2000/svg" 
              fill="none" 
              viewBox="0 0 24 24" 
              stroke="currentColor"
            >
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
            </svg>
            <svg 
              v-else-if="toast.type === 'info'" 
              class="h-6 w-6 text-blue-500" 
              xmlns="http://www.w3.org/2000/svg" 
              fill="none" 
              viewBox="0 0 24 24" 
              stroke="currentColor"
            >
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
            </svg>
            <svg 
              v-else 
              class="h-6 w-6 text-yellow-500" 
              xmlns="http://www.w3.org/2000/svg" 
              fill="none" 
              viewBox="0 0 24 24" 
              stroke="currentColor"
            >
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
            </svg>
          </div>
          <div class="ml-3 w-0 flex-1 pt-0.5">
            <p 
              :class="[
                'text-sm font-medium',
                toast.type === 'success' ? 'text-green-800' :
                toast.type === 'error' ? 'text-red-800 font-bold' :
                toast.type === 'info' ? 'text-blue-800' :
                'text-yellow-800'
              ]"
            >
              {{ toast.message }}
            </p>
          </div>
          <div class="ml-4 flex-shrink-0 flex">
            <button 
              @click="removeToast(index)" 
              class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 transition ease-in-out duration-150"
            >
              <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
              </svg>
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import { useRouter } from 'vue-router';

const toasts = ref([]);
const timers = ref(new Map()); // 使用Map存储定时器
const pausedDurations = ref(new Map()); // 存储暂停的剩余时间

// 初始化路由器以监听路由变化
const router = useRouter();

// 监听路由变化，当路由变化时清除所有toast
if (router) {
  watch(() => router.currentRoute.value, () => {
    // 在路由变化时平滑地移除所有toasts
    const toastsArray = [...toasts.value];
    for (const toast of toastsArray) {
      prepareToRemoveToast(toast.id);
    }
  });
}

// 准备移除toast（添加平滑退出动画）
const prepareToRemoveToast = (id) => {
  const index = toasts.value.findIndex(toast => toast.id === id);
  if (index !== -1) {
    // 标记为正在退出
    toasts.value[index].isExiting = true;
    
    // 添加退出动画后再移除
    setTimeout(() => {
      removeToastById(id);
    }, 300);
  }
};

// 添加一个新的toast
const addToast = (message, type = 'info', duration = 3000) => {
  // 确保duration有最小值，防止意外情况
  const minDuration = 1500;
  duration = Math.max(duration, minDuration);
  
  const id = Date.now();
  toasts.value.unshift({ 
    id, 
    message, 
    type,
    isExiting: false, // 用于控制退出动画
    createdAt: Date.now() // 记录创建时间
  });
  
  // 对于错误类型，增加显示时间
  const actualDuration = type === 'error' ? Math.max(duration, 4500) : duration;
  
  // 为成功类型确保至少显示2秒
  const finalDuration = type === 'success' ? Math.max(actualDuration, 2000) : actualDuration;
  
  // 设置定时器
  startToastTimer(id, finalDuration);
  
  // 限制最大显示数量
  if (toasts.value.length > 3) {
    const oldestToast = toasts.value.pop();
    prepareToRemoveToast(oldestToast.id);
  }
};

// 启动toast定时器
const startToastTimer = (id, duration) => {
  // 先清除已有的定时器
  if (timers.value.has(id)) {
    clearTimeout(timers.value.get(id));
  }
  
  // 存储开始时间和总持续时间
  pausedDurations.value.set(id, {
    remaining: duration,
    startTime: Date.now()
  });
  
  // 创建新的定时器
  const timer = setTimeout(() => {
    prepareToRemoveToast(id);
  }, duration);
  
  timers.value.set(id, timer);
};

// 暂停计时器（鼠标悬停时）
const pauseTimer = (id) => {
  if (timers.value.has(id) && pausedDurations.value.has(id)) {
    // 清除当前定时器
    clearTimeout(timers.value.get(id));
    
    // 计算剩余时间
    const { startTime, remaining } = pausedDurations.value.get(id);
    const elapsed = Date.now() - startTime;
    const updatedRemaining = Math.max(0, remaining - elapsed);
    
    // 更新剩余时间
    pausedDurations.value.set(id, {
      remaining: updatedRemaining,
      startTime: 0 // 标记为暂停状态
    });
  }
};

// 恢复计时器（鼠标移开时）
const resumeTimer = (id) => {
  if (pausedDurations.value.has(id)) {
    const { remaining } = pausedDurations.value.get(id);
    
    // 如果还有剩余时间，重新启动定时器
    if (remaining > 0) {
      pausedDurations.value.set(id, {
        remaining,
        startTime: Date.now()
      });
      
      const timer = setTimeout(() => {
        prepareToRemoveToast(id);
      }, remaining);
      
      timers.value.set(id, timer);
    } else {
      // 如果没有剩余时间，直接移除
      prepareToRemoveToast(id);
    }
  }
};

// 通过索引移除toast
const removeToast = (index) => {
  if (index >= 0 && index < toasts.value.length) {
    const toast = toasts.value[index];
    
    // 清除定时器
    if (timers.value.has(toast.id)) {
      clearTimeout(timers.value.get(toast.id));
      timers.value.delete(toast.id);
    }
    
    // 清除暂停记录
    if (pausedDurations.value.has(toast.id)) {
      pausedDurations.value.delete(toast.id);
    }
    
    // 移除toast
    toasts.value.splice(index, 1);
  }
};

// 通过ID移除toast
const removeToastById = (id) => {
  const index = toasts.value.findIndex(toast => toast.id === id);
  if (index !== -1) {
    removeToast(index);
  }
};

// 清理所有定时器
onUnmounted(() => {
  timers.value.forEach(timer => clearTimeout(timer));
  timers.value.clear();
  pausedDurations.value.clear();
});

// 创建用于与其他组件通信的事件总线
const toast = {
  success(message, duration) {
    addToast(message, 'success', duration);
  },
  error(message, duration) {
    addToast(message, 'error', duration);
  },
  info(message, duration) {
    addToast(message, 'info', duration);
  },
  warning(message, duration) {
    addToast(message, 'warning', duration);
  }
};

// 将toast方法导出，使其可以通过模板引用访问
defineExpose({ toast });
</script>

<style scoped>
/* 添加轻微的弹跳动画 */
@keyframes bounce-small {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
}

.animate-bounce-small {
  animation: bounce-small 0.8s ease-in-out 0.2s;
}

.animate-pulse {
  animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

/* 错误提示的特殊样式 */
.error-toast {
  box-shadow: 0 0 15px rgba(248, 113, 113, 0.3);
}
</style> 